package utils

import (
	"context"
	"fmt"
	global "gPublic/Global"

	"github.com/go-redis/redis/v8"
	"github.com/spf13/viper"
)

var (
	Red *redis.Client
)
var err error

// func InitConfig() {
// 	viper.SetConfigName("app")    // yml文件
// 	viper.AddConfigPath("config") // 路径
// 	err := viper.ReadInConfig()
// 	if err != nil {
// 		fmt.Println(err)
// 	}

// 	fmt.Println("config app inited ...")
// 	// fmt.Println("config mysql:", viper.Get("mysql"))
// 	// fmt.Println("config apl:", viper.Get("mysql.apl"))
// }

// 初始化mysql连接
// func InitMySQL() {

// 	// 控制台输出 和 sql语句
// 	newLogger := logger.New(
// 		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer（日志输出的目标，前缀和日志包含的内容——译者注）
// 		logger.Config{
// 			SlowThreshold:             time.Second, // 慢 SQL 阈值
// 			LogLevel:                  logger.Info, // 日志级别
// 			IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound（记录未找到）错误
// 			Colorful:                  true,        // 使用用彩色打印
// 		},
// 	)
// 	DB, err = gorm.Open(mysql.Open(viper.GetString("mysql.dns")), &gorm.Config{
// 		Logger: newLogger,
// 	})

// 	if err != nil {
// 		panic(err)
// 	}

// 	fmt.Println("config mysql inited ...")
// }

var ctx = context.Background()

// 初始化resis连接
func InitRedis() {

	Red = redis.NewClient(&redis.Options{
		// rdb := redis.NewClient(&redis.Options{	1
		// 	Addr: fmt.Sprintf("%s:%d", global.Config.RedisInfo.Host, global.Config.RedisInfo.Prot),
		// 	DB:   0,
		// },

		// 2
		Addr: fmt.Sprintf("%s:%d", global.Config.RedisInfo.Host, global.Config.RedisInfo.Prot),
		// DB:   global.Config.RedisInfo.Db,

		// Addr: viper.GetString("redis.host") + viper.GetString("redis.port"),
		DB: viper.GetInt("redis.db"),
		// Username:     viper.GetString("redis.username"),
		Password:     viper.GetString("redis.pwd"),
		PoolSize:     viper.GetInt("redis.poolSize"),
		MinIdleConns: viper.GetInt("redis.minIdleConn"),
	})

	pong, err := Red.Ping(ctx).Result()

	// PoolSize: 表示Redis连接池的大小，即在连接池中可以保持的最大连接数。当需要与Redis进行通信时，从连接池中获取连接来执行操作。

	// MinIdleConns: 表示Redis连接池中保持的最小空闲连接数。即使连接池中没有连接被使用，也会保持这些最小数量的连接。这有助于避免频繁地建立和销毁连接，提高性能和效率。

	if err != nil {
		// panic(err)
		fmt.Println("config redis err ...", err)
	} else {
		fmt.Println("config redis inited ...", pong)
	}
}

const (
	PublishKey = "websocket" // 渠道名称
)

// publish 发布消息到redis
func publish(ctx context.Context, channel string, msg string) error {
	fmt.Println("publish ...", msg)
	var err error
	err = Red.Publish(ctx, channel, msg).Err()
	if err != nil {
		fmt.Println("推送：", err)
	}
	return err
}

// Subscribe 订阅redis消息
func Subscribe(ctx context.Context, channel string) (string, error) {

	sub := Red.Subscribe(ctx, channel)

	msg, err := sub.ReceiveMessage(ctx)

	if err != nil {
		fmt.Println("订阅：", err)
		return "", err
	}

	messageContent := msg.Payload

	fmt.Println("Subscribe ...", messageContent)

	return messageContent, err
}

// Redis的发布订阅（Pub/Sub）是一种消息通信模式，其中消息的发送者（发布者）将消息发送到通道（channel），而订阅者可以订阅一个或多个通道，从中接收消息。下面是关于Redis发布订阅的详细说明：

// - **发布者（Publisher）**：发布者负责将消息发布到指定的通道。发布者将消息发送到通道后，所有已订阅该通道的订阅者都将收到该消息。

// - **订阅者（Subscriber）**：订阅者可以选择订阅一个或多个感兴趣的通道。一旦订阅了某个通道，订阅者将收到该通道中发出的所有消息。

// - **通道（Channel）**：通道是连接发布者和订阅者的中介，用于传递消息。每条消息都发送到一个特定的通道中，并且只有订阅该通道的订阅者才会收到消息。

// - **消息传递方式**：消息是单向传递的，即一旦发布者发布了消息到通道，所有已订阅该通道的订阅者将立即收到该消息，但发布者不会知道谁接收了该消息。

// - **消息持久化**：Redis的发布订阅机制不会保留历史消息，即订阅者只能接收到自其订阅之后发布的消息，而不会收到订阅之前发布的消息。

// - **取消订阅**：订阅者可以随时取消订阅通道，以停止接收该通道的消息。

// Redis的发布订阅模式在实时通信和消息传递中非常有用，可以用于实现即时聊天、事件通知、数据更新等功能。
